﻿using Exceptionless;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Shared.FilterHelper.Model;
using Shared.LogHelper;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Utility.Extensions;

namespace Shared.FilterHelper
{
    /// 如果同时增加 GlobalAsyncActionFilter 
    /// <summary>
    /// 同步
    /// </summary>
    public class GlobalActionFilter : IActionFilter
    {
        //private readonly ILogger _logger;

        //public GlobalActionFilter(ILoggerFactory loggerFactory)
        //{
        //    this._logger = loggerFactory.CreateLogger<GlobalActionFilter>();
        //}


        /// <summary>
        /// Action 执行之前执行
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuting(ActionExecutingContext context)
        {
            string areaName = (string)context.RouteData.Values["area"];
            string controllerName = (string)context.RouteData.Values["controller"];
            string actionName = (string)context.RouteData.Values["action"];
            //
            //this._logger.LogInformation($"{controllerName}的{actionName}开始执行了...")
            //base.OnActionExecuting(context);
            //var ip = context.HttpContext.Request.Headers["X-Forwarded-For"]
            //                ?? context.HttpContext.Request.Headers["HTTP_X_FORWARDED_FOR"]
            //                        ?? context.HttpContext.Request.Host.Host;
            //string logMsg = $"SessionID:{context.HttpContext.Session?.Id},\r\nurl:{context.HttpContext.Request.Path}\r\nParameters:{context.ActionArguments.ToJsonString()}";
            //Exceptionless.ExceptionlessClient.Default.CreateLog(logMsg, Exceptionless.Logging.LogLevel.Info).AddTags(areaName, controllerName, actionName,"Request");
        }

        /// <summary>
        /// Action 执行之后
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuted(ActionExecutedContext context)
        {
            //MyDebug.Write(MethodBase.GetCurrentMethod(), context.HttpContext.Request.Path);
            //base.OnActionExecuted(context);
           // string logMsg = $"SessionID:{context.HttpContext.Session?.Id},\r\nurl:{context.HttpContext.Request.Path}\r\nParameters:{context.HttpContext.Request.ReadFormAsync.ToJsonString()}";
           // Exceptionless.ExceptionlessClient.Default.CreateLog(logMsg, Exceptionless.Logging.LogLevel.Info).AddTags(areaName, controllerName, actionName, "Request");
        }
    }
    /// <summary>
    /// 异步
    /// </summary>
    public class GlobalAsyncActionFilter : IAsyncActionFilter
    {
        private readonly ILogger m_logger;

        public GlobalAsyncActionFilter(ILogger logger)
        {
            this.m_logger = logger;
        }
        /// <summary>
        /// 方法执行
        ///     如果同时增加 GlobalActionFilter, GlobalAsyncActionFilter 过滤器执行顺序为:
        ///     1. GlobalActionFilter.OnActionExecuting()
        ///     2. GlobalAsyncActionFilter.OnActionExecutionAsync()
        ///     3. GlobalActionFilter.OnActionExecuted()
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context
                                        , ActionExecutionDelegate next)
        {
            // Do something before the action executes.
            // next() calls the action method.

            //取参数
            //context.ActionArguments

            DateTime dateTime = DateTime.Now;

            //取结果
            //resultContext.Result
            var resultContext = await next();
            _ = WriteLogAsync(dateTime, context, resultContext);


        }

        ///// <summary>
        ///// 控制器操作结果执行之后调用此方法
        ///// </summary>
        ///// <param name="context"></param>
        //public override void OnActionExecuted(ActionExecutedContext context)
        //{
        //    base.OnActionExecuted(context);
        //}

        /// <summary>
        /// 写日志
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        private async Task WriteLogAsync(DateTime executeStartTime
                                       , ActionExecutingContext actionContext
                                       , ActionExecutedContext resultContext)
        {
            //var ip = actionContext.HttpContext.Request.Headers["X-Forwarded-For"]
            //                ?? actionContext.HttpContext.Request.Headers["HTTP_X_FORWARDED_FOR"]
            //                        ?? actionContext.HttpContext.Request.Host.Host;

            var items = actionContext.HttpContext.Items;
            WebApiLogModel logModel = new WebApiLogModel();
            logModel.ExecuteStartTime = executeStartTime;
            logModel.ExecuteEndTime = DateTime.Now;
            //获取Action 参数
            logModel.ActionParams =actionContext.ActionArguments;
            logModel.HttpRequestHeaders = actionContext.HttpContext.Request.Headers.ToString();
            logModel.HttpRequestPath = actionContext.HttpContext.Request.Path;
            logModel.HttpMethod = actionContext.HttpContext.Request.Method;
            logModel.ActionName = ((ControllerActionDescriptor)actionContext.ActionDescriptor).ActionName;
            logModel.ControllerName = ((ControllerActionDescriptor)actionContext.ActionDescriptor).ControllerName;
            logModel.TotalMilliseconds = (logModel.ExecuteEndTime - logModel.ExecuteStartTime).TotalMilliseconds;
            logModel.IP = actionContext.HttpContext.Connection.RemoteIpAddress.ToString();

            if (null != resultContext.Exception)
            {
                logModel.Exception = resultContext.Exception;
                m_logger.Error("ERROR:" + logModel.HttpRequestPath,logModel.ToJsonString(), "RequestException");
            }
            else
            {
                logModel.HttpResponse = resultContext.Result;
                m_logger.Info(logModel.HttpRequestPath,logModel.ToJsonString(),"Request");
            }
        }
    }
}
